package com.atguigu.tingshu.album.service.impl;

import com.atguigu.tingshu.album.mapper.AlbumInfoMapper;
import com.atguigu.tingshu.album.mapper.TrackInfoMapper;
import com.atguigu.tingshu.album.mapper.TrackStatMapper;
import com.atguigu.tingshu.album.service.TrackInfoService;
import com.atguigu.tingshu.album.service.VodService;
import com.atguigu.tingshu.common.constant.SystemConstant;
import com.atguigu.tingshu.common.result.Result;
import com.atguigu.tingshu.common.util.AuthContextHolder;
import com.atguigu.tingshu.model.album.AlbumAttributeValue;
import com.atguigu.tingshu.model.album.AlbumInfo;
import com.atguigu.tingshu.model.album.TrackInfo;
import com.atguigu.tingshu.model.album.TrackStat;
import com.atguigu.tingshu.model.user.UserInfo;
import com.atguigu.tingshu.model.user.UserPaidTrack;
import com.atguigu.tingshu.query.album.AlbumInfoQuery;
import com.atguigu.tingshu.query.album.TrackInfoQuery;
import com.atguigu.tingshu.user.client.UserInfoFeignClient;
import com.atguigu.tingshu.vo.album.*;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Assert;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

@Slf4j
@Service
@SuppressWarnings({"unchecked", "rawtypes"})
public class TrackInfoServiceImpl extends ServiceImpl<TrackInfoMapper, TrackInfo> implements TrackInfoService {

    @Autowired
    private TrackInfoMapper trackInfoMapper;
    @Resource
    private VodService vodService;
    @Resource
    private AlbumInfoMapper albumInfoMapper;
    @Resource
    private TrackStatMapper trackStatMapper;
    @Resource
    private UserInfoFeignClient userInfoFeignClient;

    @Transactional
    @Override
    public void saveTrackInfo(TrackInfoVo trackInfoVo) {
        TrackInfo trackInfo = new TrackInfo();
        BeanUtils.copyProperties(trackInfoVo, trackInfo);
        Long userId = AuthContextHolder.getUserId();
        trackInfo.setUserId(userId == null ? 1 : userId);
        TrackInfo preTrack = this.getOne(new LambdaQueryWrapper<TrackInfo>().eq(TrackInfo::getAlbumId, trackInfoVo.getAlbumId())
                .orderByDesc(TrackInfo::getOrderNum)
                .last("limit 1")
                .select(TrackInfo::getOrderNum));
		trackInfo.setOrderNum(preTrack == null ? 1 : preTrack.getOrderNum() + 1);
        TrackMediaInfoVo mediaInfoVo = vodService.getMediaInfo(trackInfoVo.getMediaFileId());
        if (mediaInfoVo!=null){
            trackInfo.setMediaDuration(new BigDecimal(mediaInfoVo.getDuration()));
            trackInfo.setMediaSize(mediaInfoVo.getSize());
            trackInfo.setMediaType(mediaInfoVo.getType());
            trackInfo.setMediaUrl(mediaInfoVo.getMediaUrl());
        }
        trackInfo.setSource(SystemConstant.TRACK_SOURCE_USER);
        trackInfo.setStatus(SystemConstant.ALBUM_STATUS_PASS);
        this.save(trackInfo);

        Long trackId = trackInfo.getId();
        AlbumInfo albumInfo = albumInfoMapper.selectById(trackInfoVo.getAlbumId());
        if (albumInfo!=null){
            albumInfo.setIncludeTrackCount(albumInfo.getIncludeTrackCount()+1);
            albumInfoMapper.updateById(albumInfo);
        }

        insertTrackStat(trackId,SystemConstant.TRACK_STAT_PLAY);
        insertTrackStat(trackId,SystemConstant.TRACK_STAT_COLLECT);
        insertTrackStat(trackId,SystemConstant.TRACK_STAT_COMMENT);
        insertTrackStat(trackId,SystemConstant.TRACK_STAT_PRAISE);


    }

    @Override
    public Page<TrackListVo> findUserTrackPage(Integer page, Integer limit, TrackInfoQuery trackInfoQuery) {
        Long userId = AuthContextHolder.getUserId();
        trackInfoQuery.setUserId(userId==null?1:userId);
        return trackInfoMapper.findUserTrackPage(new Page<TrackListVo>(page,limit),trackInfoQuery);
    }

    @Transactional
    @Override
    public void updateTrackInfo(Long trackId, TrackInfoVo trackInfoVo) {
        TrackInfo trackInfo = new TrackInfo();
        BeanUtils.copyProperties(trackInfoVo,trackInfo);
        Long userId = AuthContextHolder.getUserId();
        trackInfo.setUserId(userId== null ? 1 : userId);
        trackInfo.setId(trackId);
        TrackMediaInfoVo mediaInfoVo = vodService.getMediaInfo(trackInfoVo.getMediaFileId());
        if (mediaInfoVo!=null){
            trackInfo.setMediaDuration(new BigDecimal(mediaInfoVo.getDuration()));
            trackInfo.setMediaSize(mediaInfoVo.getSize());
            trackInfo.setMediaType(mediaInfoVo.getType());
            trackInfo.setMediaUrl(mediaInfoVo.getMediaUrl());
        }
        this.updateById(trackInfo);
    }

    @Transactional
    @Override
    public void removeTrackInfo(Long trackId) {
        TrackInfo trackInfo = this.getById(trackId);
        if (trackInfo==null){
            return;
        }
        this.removeById(trackId);

        trackStatMapper.delete(new LambdaUpdateWrapper<TrackStat>().eq(TrackStat::getTrackId,trackId));

        AlbumInfo albumInfo = albumInfoMapper.selectById(trackInfo.getAlbumId());
        if (albumInfo!=null){
            albumInfo.setIncludeTrackCount(albumInfo.getIncludeTrackCount()-1);
            albumInfoMapper.updateById(albumInfo);
        }

        vodService.removeMediaInfo(trackInfo.getMediaFileId());

    }

    @Override
    public Page<AlbumTrackListVo> findAlbumTrackPage(Long albumId, Integer page, Integer limit) {
        Page<AlbumTrackListVo> albumTrackListVoPage=trackInfoMapper.findAlbumTrackPage(new Page<AlbumTrackListVo>(page,limit),albumId);
        List<AlbumTrackListVo> trackListVoList = albumTrackListVoPage.getRecords();
        if (CollectionUtils.isEmpty(trackListVoList)){
            return albumTrackListVoPage;
        }
        AlbumInfo albumInfo = albumInfoMapper.selectById(albumId);
        Assert.notNull(albumInfo,"获取专辑信息失败");
        if (SystemConstant.ALBUM_PAY_TYPE_FREE.equals(albumInfo.getPayType())){
            return albumTrackListVoPage;
        }
        Integer tracksForFreeCount = albumInfo.getTracksForFree();
        List<AlbumTrackListVo> needPaidTrackList = trackListVoList.stream().filter(trackListVo -> trackListVo.getOrderNum() > tracksForFreeCount).collect(Collectors.toList());
        if (CollectionUtils.isEmpty(needPaidTrackList)){
            return albumTrackListVoPage;
        }

        Long userId = AuthContextHolder.getUserId();
        if (userId!=null){
            Result<UserInfo> userInfoResult = userInfoFeignClient.getUserInfo(userId);
            Assert.notNull(userInfoResult,"获取用户信息失败");
            UserInfo userInfo = userInfoResult.getData();
            Assert.notNull(userInfo,"获取用户信息失败");
            if (userInfo.getIsVip()==1 && userInfo.getVipExpireTime().after(new Date())
                    && SystemConstant.ALBUM_PAY_TYPE_VIPFREE.equals(albumInfo.getPayType()) ){
                return albumTrackListVoPage;
            }

            Result<Boolean> paidAlbumResult = userInfoFeignClient.isPaidAlbum(albumId);
            Assert.notNull(paidAlbumResult,"获取用户是否付费信息时失败");
            Boolean isPaidAlbum = paidAlbumResult.getData();
            if (isPaidAlbum){
                return albumTrackListVoPage;
            }

            Result<List<UserPaidTrack>> paidTrackListResult = userInfoFeignClient.getPaidTrackList(albumId);
            Assert.notNull(paidTrackListResult,"获取用户已购买的声音集合失败");
            List<UserPaidTrack> paidTrackList = paidTrackListResult.getData();
            if (CollectionUtils.isEmpty(paidTrackList)){
                needPaidTrackList.forEach(albumTrackListVo -> albumTrackListVo.setIsShowPaidMark(true));
                return albumTrackListVoPage;
            }
            List<Long> userPaidTrackIdList = paidTrackList.stream().map(UserPaidTrack::getTrackId).collect(Collectors.toList());
            needPaidTrackList.forEach(needPaidTrack->{
                if (!userPaidTrackIdList.contains(needPaidTrack.getTrackId())){
                    needPaidTrack.setIsShowPaidMark(true);
                }
            });

        }else {
            needPaidTrackList.forEach(albumTrackListVo -> albumTrackListVo.setIsShowPaidMark(true));
        }

        return albumTrackListVoPage;
    }


    void insertTrackStat(Long trackId,String type) {
        TrackStat trackStat = new TrackStat();
        trackStat.setTrackId(trackId);
        trackStat.setStatType(type);
        trackStat.setStatNum(0);
        trackStatMapper.insert(trackStat);
    }
}
